import {
  Scene,
  PerspectiveCamera,
  Mesh,
  WebGLRenderer,
  BoxGeometry,
  MeshBasicMaterial,
  TextureLoader,
  DoubleSide,
  Color,
} from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import Stats from 'three/examples/jsm/libs/stats.module'

class WoodenBox {
  constructor(ele) {
    if (!(ele instanceof HTMLElement)) {
      throw new Error('第一个参数必须传入dom元素')
    }

    // 创建场景
    this.scene = new Scene()
    this.scene.background = new Color('#2b3a42')
    // 创建相机
    this.camera = this.initCamera()
    // 创建网格
    this.mesh = this.initMesh()
    // this.mesh.name = 'littleMesh';

    this.scene.add(this.mesh)
    // console.log(this.scene.getObjectByName('littleMesh'));

    // 创建渲染器
    this.renderer = this.initRenderer()
    // 将渲染器添加到标签中
    ele.appendChild(this.renderer.domElement)

    // 添加FPS
    this.stats = new Stats();
    // console.log(stats.dom === stats.domElement);//true
    ele.appendChild(this.stats.domElement)

    this.initControls()
    this.animate()

    window.addEventListener('resize', this.onWindowResize.bind(this))
  }

  onWindowResize() {
    const camera = this.camera
    camera.aspect = window.innerWidth / window.innerHeight
    camera.updateProjectionMatrix()
    this.renderer.setSize(window.innerWidth, window.innerHeight)
  }

  initControls() {
    const cameraControls = new OrbitControls(
      this.camera,
      this.renderer.domElement
    )
    cameraControls.target.set(0, 0, 0)
    // cameraControls.maxDistance = 400;
    // cameraControls.minDistance  = 2;
    cameraControls.update()
  }

  initRenderer() {
    const renderer = new WebGLRenderer({ antialias: true })
    renderer.setSize(window.innerWidth, window.innerHeight)
    renderer.setPixelRatio(window.devicePixelRatio)
    return renderer
  }

  initCamera() {
    const camera = new PerspectiveCamera(
      70,
      window.innerWidth / window.innerHeight,
      1,
      1000
    )
    // 相机设置的位置和几何图形大小又一定关系
    // camera.position.set(0, 0, 3);
    camera.position.z = 3
    return camera
  }

  initMesh() {
    // 创建几何
    const geo = new BoxGeometry(1, 1, 1)
    // 创建加载器，加载材质
    const texture = new TextureLoader()
    const boxTexture = texture.load('./images/box_texture.png')
    const material = new MeshBasicMaterial({
      map: boxTexture,
      side: DoubleSide,
    })

    return new Mesh(geo, material)
  }

  animate() {
    requestAnimationFrame(this.proxy(this.animate, this))
    this.mesh.rotation.y += 0.005
    this.mesh.rotation.x += 0.01
    this.renderer.render(this.scene, this.camera)
    this.stats.update()
  }

  proxy(fn, context) {
    return () => {
      fn.apply(context)
    }
  }
}

export default WoodenBox
